package ilender.dispatching;

import java.io.*;
import java.net.*;
import java.util.Properties;

import javax.servlet.*;
import javax.servlet.http.*;

import lombok.*;

import org.apache.commons.lang3.StringEscapeUtils;
import org.apache.ibatis.session.*;
import com.google.gson.*;

import ilender.util.*;
import ilender.mappers.*;
import ilender.models.*;
import ilender.facebook.*;

/**
 * The entry point for the application.
 */
public class CanvasServlet extends HttpServlet{

	/**
	 * Accepts the initial POST request from Facebook.
	 *
	 * @param request The HTTP request object.
	 * @param response The HTTP response object.
	 */
	public void doPost(HttpServletRequest request,HttpServletResponse response) throws IOException,ServletException{
		//Parsing the JSON data from facebook.
		String signedRequest=request.getParameter("signed_request");
		String[] signedRequestTokens=signedRequest.split("\\.",2);
		String signedRequestData=Base64Url.decode(signedRequestTokens[1]);
		JsonParser parser=new JsonParser();
		JsonObject srd=(JsonObject)parser.parse(signedRequestData);

		//Redirecting user to authorize app if not already authorized.
		if(null==request.getParameter("code") || null==srd.get("user_id")){
			redirectToAuthentication(request,response);
			return;
		}

		//Passing attributes to JSP for making global javascript variables.
		Long facebookUserId=srd.getAsJsonPrimitive("user_id").getAsLong();
		Properties fbProps=PropertiesTools.fetchFacebookProperties();
		request.setAttribute("facebookUserId",facebookUserId);
		request.setAttribute("appId",fbProps.getProperty("app-id"));
		request.setAttribute("appUrl",fbProps.getProperty("app-url"));

		request.setAttribute("listFiles_js",listFilesIn("/js"));
		request.setAttribute("listFiles_css",listFilesIn("/css"));
		request.setAttribute("listFiles_css_common",listFilesIn("/css_common"));

		if(null!=request.getSession().getAttribute("fbref")){
			request.setAttribute("fbref",request.getSession().getAttribute("fbref"));
			request.getSession().removeAttribute("fbref");
		}

		try(SqlSession session=MyBatisTools.openSession()){
			val usersMapper=session.getMapper(UsersMapper.class);
			MUser user=usersMapper.find(facebookUserId);
			if(null==user){
				user=new MUser();
				user.setId(facebookUserId);
				val userData=GraphAPI.getInstance().getUserData(facebookUserId,"name");
				user.setName(userData.get("name").getAsString());
				usersMapper.insert(user);//Can't user `user.save(usersMapper)` because we already have ID.
				session.commit();
			}
		}catch(Exception e){
			throw new RuntimeException(e);
		}

		//Rendering the layout.
		request.getRequestDispatcher("/WEB-INF/jsp/canvas/layout.jsp").forward(request,response);
	}

	/**
	 * Redirects the user to the Facebook authentication form. Called with the
	 * request and response of the original HTTP request.
	 *
	 * @param request the JSON request.
	 * @param response The HTTP response object.
	 */
	public void redirectToAuthentication(HttpServletRequest request,HttpServletResponse response) throws IOException,ServletException{
		Properties fbProps=PropertiesTools.fetchFacebookProperties();
		request.setAttribute("app-id",fbProps.getProperty("app-id"));
		request.setAttribute("redirect-url",fbProps.getProperty("app-url"));
		request.setAttribute("scope","publish_actions");
		//request.setAttribute("state",URLEncoder.encode(request.getParameter("fb_ref")));
		if(null!=request.getParameter("fb_ref")){
			request.getSession().setAttribute("fbref",request.getParameter("fb_ref"));
		}
		request.getRequestDispatcher("/WEB-INF/jsp/fb_authenticate_redirect.jsp").forward(request,response);
	}

	/**
	 * Exactly what it says on tin.
	 *
	 * @param targetPath the folder to list it's files.
	 * @return an iterable of the files in that folder.
	 */
	private Iterable<String> listFilesIn(String targetPath){
		return getServletConfig().getServletContext().getResourcePaths(targetPath);
	}
}
